﻿namespace UnityEditor
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using UnityEditorInternal;
    using UnityEngine;

    internal class HierarchyPropertyTreeViewDataSource : DefaultTreeViewDataSource
    {
        private bool m_FoldersOnly;
        private HierarchyType m_HierarchyType;

        public HierarchyPropertyTreeViewDataSource(TreeView treeView) : base(treeView)
        {
            this.m_HierarchyType = HierarchyType.Assets;
            base.m_ShowRootNode = false;
            base.m_RootIsCollapsable = false;
        }

        private static string CreateDisplayName(int instanceID)
        {
            return Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(instanceID));
        }

        public override void FetchData()
        {
            string path = "Assets";
            int instanceIDFromGUID = AssetDatabase.GetInstanceIDFromGUID(AssetDatabase.AssetPathToGUID(path));
            int depth = 0;
            base.m_RootNode = new TreeView.Node(instanceIDFromGUID, depth, null, CreateDisplayName(instanceIDFromGUID));
            this.SetExpanded(base.m_RootNode, true);
            IHierarchyProperty property = new HierarchyProperty(this.m_HierarchyType);
            property.Reset();
            int[] expanded = base.expandedInstanceIDs.ToArray();
            Texture2D textured = EditorGUIUtility.FindTexture(EditorResourcesUtility.emptyFolderIconName);
            base.m_VisibleRows = new List<TreeView.Node>();
            while (property.Next(expanded))
            {
                if (!this.m_FoldersOnly || property.isFolder)
                {
                    TreeView.Node item = new TreeView.Node(property.instanceID, property.depth, null, property.name);
                    if (property.isFolder && !property.hasChildren)
                    {
                        item.icon = textured;
                    }
                    else
                    {
                        item.icon = property.icon;
                    }
                    if (property.hasChildren)
                    {
                        item.children = new TreeView.Node[1];
                    }
                    base.m_VisibleRows.Add(item);
                }
            }
            SetChildParentReferences(base.m_VisibleRows, base.m_RootNode);
            base.m_NeedRefreshVisibleFolders = false;
            bool revealSelectionAndFrameLastSelected = false;
            base.m_TreeView.SetSelection(Selection.instanceIDs, revealSelectionAndFrameLastSelected);
        }

        public override TreeView.Node FindNodeByID(int instanceID)
        {
            IHierarchyProperty property = new HierarchyProperty(this.m_HierarchyType);
            if (!property.Find(instanceID, null))
            {
                return null;
            }
            while (property.Parent())
            {
                this.SetExpandedByInstanceID(property.instanceID, true);
            }
            if (base.m_NeedRefreshVisibleFolders)
            {
                this.FetchData();
            }
            return base.FindNodeByID(instanceID);
        }

        private static TreeView.Node FindParent(List<TreeView.Node> visibleNodes, int childDepth, int childIndex)
        {
            if (childDepth != 0)
            {
                while (childIndex >= 0)
                {
                    TreeView.Node node = visibleNodes[childIndex];
                    if (node.depth == (childDepth - 1))
                    {
                        return node;
                    }
                    childIndex--;
                }
            }
            return null;
        }

        public override List<TreeView.Node> GetVisibleRows()
        {
            if ((base.m_VisibleRows == null) || base.m_NeedRefreshVisibleFolders)
            {
                this.FetchData();
                base.m_NeedRefreshVisibleFolders = false;
                base.m_TreeView.Repaint();
            }
            return base.m_VisibleRows;
        }

        public bool IsShowingFoldersOnly()
        {
            return this.m_FoldersOnly;
        }

        internal static void SetChildParentReferences(List<TreeView.Node> visibleNodes, TreeView.Node root)
        {
            for (int i = 0; i < visibleNodes.Count; i++)
            {
                TreeView.Node child = visibleNodes[i];
                TreeView.Node parent = FindParent(visibleNodes, child.depth, i);
                if (parent == null)
                {
                    parent = root;
                }
                SetParent(child, parent);
            }
        }

        public override bool SetExpandedByInstanceID(int instanceID, bool expand)
        {
            if (base.SetExpandedByInstanceID(instanceID, expand))
            {
                InternalEditorUtility.expandedProjectWindowItems = base.expandedInstanceIDs.ToArray();
                return true;
            }
            return false;
        }

        public override void SetExpandedWithChildren(TreeView.Node node, bool expand)
        {
            HashSet<int> source = new HashSet<int>(base.expandedInstanceIDs);
            HashSet<int> other = new HashSet<int>();
            IHierarchyProperty property = new HierarchyProperty(this.m_HierarchyType);
            if (property.Find(node.instanceID, null))
            {
                other.Add(node.instanceID);
                int depth = property.depth;
                while (property.Next(null) && (property.depth > depth))
                {
                    if (property.hasChildren)
                    {
                        other.Add(property.instanceID);
                    }
                }
            }
            if (expand)
            {
                source.UnionWith(other);
            }
            else
            {
                source.ExceptWith(other);
            }
            this.SetExpandedInstanceIDs(source.ToArray<int>());
            InternalEditorUtility.expandedProjectWindowItems = base.expandedInstanceIDs.ToArray();
        }

        private static void SetParent(TreeView.Node child, TreeView.Node parent)
        {
            child.parent = parent;
            List<TreeView.Node> list = new List<TreeView.Node>(parent.children);
            if ((list.Count > 0) && (list[0] == null))
            {
                list.RemoveAt(0);
            }
            list.Add(child);
            parent.children = list.ToArray();
        }

        public void SetShowFolderOnly(bool enable)
        {
            this.m_FoldersOnly = enable;
        }
    }
}

